package com.abu.course.service.impl;

import cn.hutool.core.collection.CollectionUtil;
import cn.hutool.core.convert.Convert;
import cn.hutool.core.util.StrUtil;
import com.abu.common.Resp;
import com.abu.common.exception.CRException;
import com.abu.course.client.ClassesClient;
import com.abu.course.client.ClassroomClient;
import com.abu.course.mapper.CourseMapper;
import com.abu.course.pojo.Course;
import com.abu.course.pool.CourseThreadPoolExecutor;
import com.abu.course.service.CourseService;
import com.abu.course.vo.ClassroomOrderVO;
import com.abu.course.vo.CourseVo;
import com.abu.course.vo.QueryConditionSelect;
import com.abu.course.vo.QueryCourseVo;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.util.CollectionUtils;
import org.springframework.util.StringUtils;

import java.time.Duration;
import java.time.LocalDateTime;
import java.util.HashMap;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.ThreadPoolExecutor;
import java.util.stream.Collectors;

/**
 * <p>
 * 课程表 服务实现类
 * </p>
 *
 * @author 阿布
 * @since 2021-02-03
 */
@Slf4j
@Service
public class CourseServiceImpl extends ServiceImpl<CourseMapper, Course> implements CourseService {

    @Autowired
    private ClassroomClient classroomClient;

    @Autowired
    private ClassesClient classesClient;

    @Autowired
    private CourseMapper courseMapper;

    @Autowired
    private ThreadPoolExecutor threadPoolExecutor;


    @Override
    public HashMap<String, Object> queryPageByCondition(QueryCourseVo queryCourseVo) {
//          获取参数
        Long page = queryCourseVo.getPage();
        Long limit = queryCourseVo.getLimit();
        if (page == null) {
            page = 1L;
        }
        if (limit == null) {
            limit = 6L;
        }
        LocalDateTime startTime = queryCourseVo.getStartTime();
        LocalDateTime endTime = queryCourseVo.getEndTime();
        List<Course> courseList = null;
        Integer total = null;
//        如果时间不为空，则按时间执行查询
        if (startTime != null && endTime != null) {
            courseList = this.courseMapper.selectBetweenBeginTimeAndEndTime(page, limit, startTime, endTime);
            total = this.courseMapper.selectBetweenBeginTimeAndEndTimeTotal(startTime, endTime);
//       否则就查询全部
        } else {
            courseList = this.courseMapper.selectPageNonCondition(page, limit);
            total = this.courseMapper.selectTotal();
        }

//        判断查询数据是否为空
        if (CollectionUtils.isEmpty(courseList)) {
            throw new CRException("数据为空", 404);
        }
        List<CourseVo> courseVoList = courseList.stream().map(course -> {
            CourseVo courseVo = new CourseVo();
            BeanUtils.copyProperties(course, courseVo);
//        获取课程的教室名字
            Resp respClassroom = this.classroomClient.getClassroom(course.getClassroomId());
            Integer code = respClassroom.getCode();
            if (code == 1) {
                LinkedHashMap classroomMap = (LinkedHashMap) respClassroom.getData().get("classroom");
                String name = (String) classroomMap.get("classroomName");
                courseVo.setClassroomName(name);
            }
//        获取班级的名字
            Long classId = course.getClassId();
            Resp respClasses = this.classesClient.queryClassNameByClassId(classId);
            Integer codeClass = respClasses.getCode();
            if (codeClass == 503) {
                throw new CRException("服务暂时不可用", 503);
            }
            if (codeClass == 1) {
                LinkedHashMap classroomMap = (LinkedHashMap) respClasses.getData().get("classes");
                String className = (String) classroomMap.get("className");
                courseVo.setClassName(className);
            }
//        计算时长
            LocalDateTime begin = course.getBeginTime();
            LocalDateTime end = course.getEndTime();
//            获取时差
            Duration duration = Duration.between(begin, end);
            long seconds = duration.getSeconds();
            Float durationSeconds = Convert.toFloat(seconds);
            courseVo.setDuration(durationSeconds / 60);
            return courseVo;
        }).collect(Collectors.toList());
//        返回结果集
        HashMap<String, Object> hashMapResult = new HashMap<>(2);
        hashMapResult.put("total", total);
        hashMapResult.put("courseVoList", courseVoList);
        return hashMapResult;
    }

    @Override
    public Course getCourseById(Long id) {
        return this.getOne(new QueryWrapper<Course>().eq("course_id", id));
    }

    @Override
    public Boolean modifiedClassroom(Course course) {
        return this.updateById(course);
    }

    @Override
    public boolean deleteCourse(Long id) {
        return this.removeById(id);
    }

    @Override
    public Boolean saveCourse(Course course) {
        Boolean flag = this.checkData(course.getClassroomId(), course.getBeginTime(), course.getEndTime());
        if (!flag) {
            throw new CRException("时间有冲突，请更换教室或时间段");
        }
        return this.save(course);
    }

    @Override
    public Boolean checkData(Long id, LocalDateTime beginTime, LocalDateTime endTime) {
//        判断该时间段中班级是否空闲
        List<Course> courseList = this.courseMapper.selectCourseIsExists(id, beginTime, endTime);
        return CollectionUtil.isEmpty(courseList);
    }

    @Override
    public HashMap<String, Object> queryAllHistory(QueryConditionSelect queryConditionSelect) {
        Long page = queryConditionSelect.getPage();
        Long size = queryConditionSelect.getSize();
        String classroomName = queryConditionSelect.getName();
        HashMap<String, Object> hashMap = new HashMap<>(2);
//            普通分页查询所有
        List<Course> applyReportList = this.courseMapper.selectPages(page, size, classroomName);
        if (CollectionUtils.isEmpty(applyReportList)) {
            throw new CRException("数据为空", 404);
        }
        Integer total = this.courseMapper.selectTotalSimple(classroomName);
//        查询一共多少条
        hashMap.put("total", total);
        hashMap.put("applyReportList", applyReportList);
        return hashMap;
    }

    @Override
    public HashMap<String, Object> queryHistoryByCondition(QueryConditionSelect queryConditionSelect) {
        LocalDateTime beginTime = queryConditionSelect.getBeginTime();
        LocalDateTime endTime = queryConditionSelect.getEndTime();
        List<Course> applyReportList;
        String classroomName = queryConditionSelect.getName();
        HashMap<String, Object> hashMap = null;
//        按时间条件查询
        if (beginTime != null && endTime != null) {
//        判断开始时间是否大于结束时间
            if (endTime.isBefore(beginTime)) {
                throw new CRException("结束时间 要大于 开始时间", 400);
            }
            applyReportList = this.courseMapper.selectPageByCondition(classroomName, beginTime, endTime);
            Integer total = this.courseMapper.selectCountByCondition(classroomName, beginTime, endTime);
            if (CollectionUtils.isEmpty(applyReportList)) {
                throw new CRException("当前教室没有被预约过", 404);
            }
            hashMap = new HashMap<>(2);
//        查询一共多少条
            hashMap.put("total", total);
            hashMap.put("courseApplyList", applyReportList);
            return hashMap;
        }
        return hashMap;
    }

    @Override
    public List<ClassroomOrderVO> getClassroomOrderByClassroomName(String classroomName) {
        return this.courseMapper.getClassroomOrderByClassroomName(classroomName);
    }

    @Override
    public HashMap<String, Object> queryPageOnlyCourse(QueryCourseVo queryCourseVo) {
//        1.获取参数
        Long page = queryCourseVo.getPage();
        Long limit = queryCourseVo.getLimit();
        LocalDateTime startTime = queryCourseVo.getStartTime();
        LocalDateTime endTime = queryCourseVo.getEndTime();
        String searchParam = queryCourseVo.getSearchParam();
        Long queryClassId = queryCourseVo.getClassId();
        String type = queryCourseVo.getType();
//        2.分页条件
        Page<Course> classroomPage = new Page<>(page, limit);
//        3.查询条件
        QueryWrapper<Course> queryWrapper = new QueryWrapper<>();
//        3.1查询的字段
        queryWrapper.select("course_name", "classroom_id", "teacher_name", "begin_time", "end_time", "class_id");
//        3.2查询类型
        if (!StringUtils.isEmpty(type)) {
            switch (type) {
                case "1":
                    queryWrapper.like(!StringUtils.isEmpty(searchParam), "course_name", searchParam);
                    break;
                case "2":
                    queryWrapper.like(!StringUtils.isEmpty(searchParam), "teacher_name", searchParam);
                    break;
                default:
                    break;
            }
        }
//         3.3查询时间
        queryWrapper
                .ge(startTime != null, "begin_time", startTime)
                .le(endTime != null, "end_time", endTime);
//         3.4按班级id查询
        queryWrapper.eq(queryClassId != null, "class_id", queryClassId);
//        4.执行查询
        Page<Course> pageCourse = this.page(classroomPage, queryWrapper);
//        5.构造结果集
        List<Course> courseList = pageCourse.getRecords();
        if (CollectionUtils.isEmpty(courseList)) {
            throw new CRException("数据为空", 404);
        }
        long total = pageCourse.getTotal();
        List<CourseVo> courseVoList = courseList.stream().map(course -> {
            CourseVo courseVo = new CourseVo();
            Long classroomId = course.getClassroomId();

//            5.1使用线程池优化获取教室信息
            CompletableFuture<Resp> classroomResult = CompletableFuture.supplyAsync(() -> this.classroomClient.getClassroom(classroomId), threadPoolExecutor);
            Resp respClassroom = null;
            try {
                respClassroom = classroomResult.get();
            } catch (InterruptedException | ExecutionException e) {
                log.error("获取结果失败，{}", e.getMessage());
            }
            BeanUtils.copyProperties(course, courseVo);
//            获取当前课程教室信息
            if (respClassroom.getCode() == 1) {
                LinkedHashMap mapClassroom = (LinkedHashMap) respClassroom.getData().get("classroom");
                courseVo.setClassroomName((String) mapClassroom.get("classroomName"));
            }
//            获取当前课程班级信息
            Long classId = course.getClassId();

//            5.2使用线程池优化获取教室信息
            CompletableFuture<Resp> classesResult = CompletableFuture.supplyAsync(() -> this.classesClient.queryClassNameByClassId(classId), threadPoolExecutor);
            Resp resp = null;
            try {
                resp = classesResult.get();
            } catch (InterruptedException | ExecutionException e) {
                log.error("获取结果失败，{}", e.getMessage());
            }
            Integer classCode = resp.getCode();
            String msg = resp.getMsg();
            if (classCode == 503) {
                throw new CRException(msg, classCode);
            }
            LinkedHashMap mapClass = (LinkedHashMap) resp.getData().get("classes");
            String className = (String) mapClass.get("className");
            courseVo.setClassName(className);
            return courseVo;
        }).collect(Collectors.toList());

//        返回结果集
        HashMap<String, Object> mapResult = new HashMap<>(2);
        mapResult.put("total", total);
        mapResult.put("courseVoList", courseVoList);
        return mapResult;
    }
}
